package com.palrevo.data.services;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.palrevo.data.dao.DAO;
import com.palrevo.data.dao.DAOFactory;
import com.palrevo.data.dao.DaoRecord;
import com.palrevo.data.dao.DataException;
import com.palrevo.data.models.Menu;
import com.palrevo.data.models.MenuItem;
import com.palrevo.data.models.Page;
import com.palrevo.utils.Log;


/**
 * 
 * 
 * @author AAsha
 * 
 */
public class PagesDBService extends ServiceBase {
	
	
	/**
	 * 
	 */
	private PagesDBService(){
	}
	
	/**
	 * 
	 * @author AAsha
	 *
	 */
	private static class SingletonHolder{
		private static PagesDBService instance = new PagesDBService(); 
	}
	
	/**
	 * 
	 * @return PageContentsService instance
	 */
	public static PagesDBService getInstance(){
		return SingletonHolder.instance;
	}
	
	
	/**
	 * 
	 * @param pageId
	 * @return Page
	 * @throws DataException
	 */
	public Page loadPage(Integer pageId) throws DataException{
		
		DAO dao = DAOFactory.getInstance().createDao();
		
		List<String> fields = new ArrayList<String>();
		fields.add(Columns.TITLE.name());
		fields.add(Columns.BODY.name());
		
		List<String> keys = new ArrayList<String>();
		keys.add(Columns.ID.name());
		
		Map<Integer, Object> params = new HashMap<Integer, Object>();
		params.put(1, pageId);
		
		dao.selectWhere(Tables.pages.name(), fields , keys, params);
		
		Page page = null;
		
		for(DaoRecord record:dao.getResult()){
			
			page = new Page();
			page.setTitle(record.getValue(Columns.TITLE.name()).toString());
			page.setBody(record.getValue(Columns.BODY.name()).toString());
		}
		
		
		return page;
	}
	
	/**
	 * 
	 * @return content pages
	 * @throws DataException
	 */
	public Map<Long,Page> loadContentPages() throws DataException{
		
		Map<Long,Page> pages = new HashMap<Long, Page>();
		
		try{
			
			DAO dao = DAOFactory.getInstance().createDao();
			
			String sql = "SELECT * FROM " + Tables.pages.name();

			dao.execute(sql);
			
			Page page = null;
			
			for(DaoRecord record:dao.getResult()){
				
				page = new Page();
				page.setId(Long.valueOf( record.getValue(Columns.ID.name()).toString() ));
				page.setTitle(record.getValue(Columns.TITLE.name()).toString());
				page.setBody(record.getValue(Columns.BODY.name()).toString());
				page.setIcon(record.getValue(Columns.ICON.name()));
				
				pages.put(page.getId(), page);
			}
			
		}catch(Exception ex){
			Log.error(this, ex.getMessage());
			throw new DataException(ex.getMessage(), ex);
		}
		
		
		return pages;
	}
	
	/**
	 * 
	 * @return site menu
	 * @throws DataException
	 */
	public Menu loadMenu() throws DataException{
		
		Menu menu = null;
		
		try{
			
			DAO dao = DAOFactory.getInstance().createDao();
			
			String sql = "SELECT * FROM " + Tables.menu_items.name();
			dao.execute(sql);
			
			menu = new Menu();
			List<MenuItem> items = new ArrayList<MenuItem>();
			MenuItem menuItem = null;
			LinkedHashMap<Integer, MenuItem> menuItemsMap = new LinkedHashMap<Integer, MenuItem>();
			Map<Long,LinkedHashMap<Integer, MenuItem>> parentsLeafs = new HashMap<Long,LinkedHashMap<Integer, MenuItem>>();
			
			for(DaoRecord record:dao.getResult()){
				menuItem = new MenuItem();
				menuItem.setId(Long.valueOf(record.getValue(Columns.ID.name()).toString()));
				menuItem.setPageId(record.getValue(Columns.PAGE_ID.name()));
				menuItem.setIndex(Integer.valueOf(record.getValue(Columns.INDEX.name()).toString()));
				menuItem.setLeaf((Boolean) record.getValue(Columns.IS_LEAF.name()));
				menuItem.setTitle(record.getValue(Columns.TITLE.name()).toString());
				menuItem.setParentId(record.getValue(Columns.PARENT_ID.name()));
				items.add(menuItem);
				
				if(menuItem.getParentId() != null){
					
					if(!parentsLeafs.containsKey(menuItem.getParentId())){
						parentsLeafs.put(menuItem.getParentId(), new LinkedHashMap<Integer, MenuItem>());
					}
					parentsLeafs.get(menuItem.getParentId()).put(menuItem.getIndex(), menuItem);
					
					if(!menuItem.getLeaf()){
						if(!parentsLeafs.containsKey(menuItem.getId())){
							parentsLeafs.put(menuItem.getId(), new LinkedHashMap<Integer, MenuItem>());
						}
					}
				}else{
					menuItemsMap.put(menuItem.getIndex(), menuItem);
					if(!menuItem.getLeaf()){
						if(!parentsLeafs.containsKey(menuItem.getParentId())){
							parentsLeafs.put(menuItem.getParentId(), new LinkedHashMap<Integer, MenuItem>());
						}
					}
				}
				
			}
			
			for(MenuItem item:items){
				if(parentsLeafs.containsKey(item.getId())){
					item.setMenuItems(new ArrayList<MenuItem>(parentsLeafs.get(item.getId()).values()));
				}
			}
			
			menu.setItems(new ArrayList<MenuItem>(menuItemsMap.values()));
			
		}catch(Exception ex){
			Log.error(this, ex.getMessage());
			throw new DataException(ex.getMessage(), ex);
		}
		
		return menu;
	}
	
	/**
	 * 
	 * @param page
	 * @throws DataException
	 */
	public Page addPage(Page page) throws DataException{
		
		try{
			
			DAO dao = DAOFactory.getInstance().createDao();
			
			//Add Page
			String sql = "INSERT INTO "+ Tables.pages.name() +" (TITLE, BODY) VALUES ('"+ page.getTitle() +"', '"+ page.getBody() +"')";
			dao.executeUpdate(sql);
			
			//Get Newly added page Id
			Long pageId = Long.valueOf(getLastInsertedRecordId().toString()); 
			
			page.setId(pageId);
			
		}catch(Exception ex){
			Log.error(this, ex.getMessage());
			throw new DataException(ex.getMessage(), ex);
		}
		
		return page;
	}
	
	/**
	 * 
	 * @param page
	 * @throws DataException
	 */
	public void updatePage(Page page) throws DataException{
		
		try{
			
			DAO dao = DAOFactory.getInstance().createDao();
			
			//Edit Page
			String sql = "UPDATE "+ Tables.pages.name() +" SET TITLE = '"+ page.getTitle()  +"' , BODY = '"+ page.getBody() +"' WHERE ID = " + page.getId();
			dao.executeUpdate(sql); 
			
		}catch(Exception ex){
			Log.error(this, ex.getMessage());
			throw new DataException(ex.getMessage(), ex);
		}
		
	}
	
	/**
	 * 
	 * @param page
	 * @throws DataException
	 */
	public void deletePage(Page page) throws DataException{
		
		try{
			
			DAO dao = DAOFactory.getInstance().createDao();
			
			//Delete Page
			String sql = "DELETE FROM  "+ Tables.pages.name() +" WHERE ID = " + page.getId();
			dao.executeUpdate(sql);
			
		}catch(Exception ex){
			Log.error(this, ex.getMessage());
			throw new DataException(ex.getMessage(), ex);
		}
		
	}
	
}
